﻿using Client;
using Newtonsoft.Json;
using Shared.Method;
using Shared.Model;
using StationClient.Dialog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace StationClient
{
    public partial class FormBackGround : Form
    {
        private FormStation _formSta = null;//上一个界面
        private STATION _sta = null;//当前工位信息
        //private List<PRODUCT> _listProduct = null;
        private List<PROCESS> _listProcess = null;
        private List<PRODUCT> _listProduct = null;
        private List<NODE> _listNode = null;

        //private YcdStrTcpServer _tcpServer = null;

        private ServerTcp _serverTcp = null;

        public FormBackGround(FormStation formSta, STATION sta)
        {
            //获得当前电脑的MAC地址
            _sta = sta;
            _formSta = formSta;
            _listProcess = new List<PROCESS>();
            _listProduct = new List<PRODUCT>();

            InitializeComponent();
        }

        private void FormBackGround_Load(object sender, EventArgs e)
        {
            NODE nodeW = new NODE();
            var selectNode = MethodWcf.SelectNodeClient(nodeW);
            if (selectNode.result)
            {
                _listNode = selectNode.value;
            }

            ////创建一个TCP监听客户端
            //_tcpServer = new YcdStrTcpServer();

            ////接收数据，分离数据为三个端口的
            //_tcpServer.OnAccept += _tcpServer_OnAccept;
            //_tcpServer.OnReceive += _tcpServer_OnReceive;
            //_tcpServer.OnError += _tcpServer_OnError;

            //_tcpServer.Start();

            _serverTcp = new ServerTcp(20, 0x200000);
            _serverTcp.Init();
            _serverTcp.SetPacketOn();

            _serverTcp.OnAcceptHandler += _serverTcp_OnAcceptHandler;
            _serverTcp.OnReceiveHandler += _serverTcp_OnReceiveHandler;
            _serverTcp.OnErrorHandler += _serverTcp_OnErrorHandler;
            _serverTcp.OnCloseHandler += _serverTcp_OnCloseHandler;
            _serverTcp.OnSendHandler += _serverTcp_OnSendHandler;

            _serverTcp.Start(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 26398));

            //等比例缩放
            X = this.Width;
            Y = this.Height;

            setTag(this);

            this.Resize += new EventHandler(Form_Resize);
        }

        private void _serverTcp_OnSendHandler(string message)
        {
            AppendRichTextBox(message);
        }

        private void _serverTcp_OnCloseHandler(string message)
        {
            AppendRichTextBox(message);
        }

        private void _serverTcp_OnErrorHandler(string message)
        {
            AppendRichTextBox(string.Format("错误信息是：{0}", message));
        }

        private void _serverTcp_OnReceiveHandler(System.Net.Sockets.Socket recvSocket, byte[] recvBytes, int offset, int length)
        {
            string recvMsg = Encoding.UTF8.GetString(recvBytes, offset, length);

            AppendRichTextBox($"recv length:{length}");

            //分类数据
            if (string.IsNullOrEmpty(recvMsg) || recvMsg.Length <= 33)
            {

                //TcpSendMsg("KEEP", null, clientNum);
                return;//抛弃小于33个字符的数据
            }
            //分类处理方法
            string methodFlag = recvMsg.Substring(0, 1);

            //string guid = recvMsg.Substring(1, 32);
            string jsonMsg = recvMsg.Substring(1);

            //AppendRichTextBox(jsonMsg);

            try
            {
                //超级后台，直接返回成功
                if (checkBoxBigBackGround.Checked)
                {
                    ReturnMessage retMsg = new ReturnMessage()
                    {
                        RetResult = true,
                        Message = "超级后台不走过站流程，不写日志",
                        ProductMac = "666666666666"
                    };

                    TcpSendMsg(JsonConvert.SerializeObject(retMsg), recvSocket);
                    return;
                }

                //分类
                if (methodFlag == SharedData.CAN_TEST)
                {
                    AppendRichTextBox("客户端请求测试");
                    ReturnMessage msg = JsonConvert.DeserializeObject<ReturnMessage>(jsonMsg);
                    IfCanTest(msg, recvSocket);
                }
                else if (methodFlag == SharedData.TEST_RESULT)
                {
                    AppendRichTextBox("客户端返回测试结果");
                    TestResultMsg msg = JsonConvert.DeserializeObject<TestResultMsg>(jsonMsg);
                    SaveTestResultMsg(msg, recvSocket);
                }
                else if (methodFlag == SharedData.SAVE_TEST_DATA)
                {
                    AppendRichTextBox("客户端写测试数据");
                    TestSaveLog msg = JsonConvert.DeserializeObject<TestSaveLog>(jsonMsg);
                    SaveTestLog(msg, recvSocket);
                }
            }
            catch (Exception ex)
            {
                AppendRichTextBox(string.Format("获取数据出错，错误代码为：{0}", ex.Message));

                var retMsg = new ReturnMessage();

                retMsg.Message = string.Format("获取数据出错，错误代码为：{0}", ex.Message);
                retMsg.RetResult = false;

                TcpSendMsg(JsonConvert.SerializeObject(retMsg), recvSocket);
            }
        }

        private void _serverTcp_OnAcceptHandler(System.Net.Sockets.Socket sock, string message)
        {
            AppendRichTextBox($"{message}");
        }

        private void _tcpServer_OnError(string obj)
        {
            AppendRichTextBox(string.Format("错误信息是：{0}", obj));
        }

        private void TcpSendMsg(/*string guid,*/ string msg, System.Net.Sockets.Socket socket)
        {
            //if (_tcpServer == null) return;
            //_tcpServer.SendData(clientNum, string.Format("{0}{1}", guid, msg));

            _serverTcp.SendBytes(socket,
                Encoding.UTF8.GetBytes(msg));
        }

        /// <summary>
        /// 分类信息
        /// </summary>
        /// <param name="recvMsg"></param>
        /// <param name="clientNum"></param>
        private void _tcpServer_OnReceive(string recvMsg, int clientNum)
        {

        }

        //判断能否测试
        private void IfCanTest(/*string guid,*/ ReturnMessage msg, System.Net.Sockets.Socket socket)
        {
            if (/*string.IsNullOrEmpty(guid) || */msg == null)
            {
                AppendRichTextBox("IFCANTEST ERROR，guid空或CanTestMsg为空");
                return;
            }

            //判断是否是YCD内部MAC
            bool isYcdMac = false;

            if (msg.ProductMac.ToUpper().StartsWith(SharedData.YCD_MAC_EPON_START) || msg.ProductMac.ToUpper().StartsWith(SharedData.YCD_MAC_GPON_START))
            {
                isYcdMac = true;
            }

            //查询MAC下产品的数量
            PRODUCT product = new PRODUCT();
            product.SetWhere();

            if (isYcdMac == false)
                product.MAC = msg.ProductMac;
            else
                product.YCD_MAC = msg.ProductMac;

            var proRes = MethodWcf.SelectProductCountClient(product);

            if (!proRes.result)//如果不能获得产品信息，写错误信息到框中
            {
                AppendRichTextBox(proRes.message);
                msg.RetResult = false;
                msg.Message = proRes.message;

                TcpSendMsg(/*guid, */JsonConvert.SerializeObject(msg), socket);
                return;
            }

            //不存在的话，写入产品数据
            int pro_num = 0;
            if (!int.TryParse(proRes.message, out pro_num))
            {
                AppendRichTextBox(string.Format("未能获得此MAC下的产品数量信息，MAC：{0}", msg.ProductMac));
                msg.RetResult = false;
                msg.Message = string.Format("未能获得此MAC下的产品数量信息，MAC：{0}", msg.ProductMac);

                TcpSendMsg(/*guid, */JsonConvert.SerializeObject(msg), socket);
                return;
            }

            //PRODUCT product = new PRODUCT();
            if (pro_num == 0)//没有产品信息
            {
                //写入产品信息
                product.SetUpdate();//写产品信息用

                if (isYcdMac == false)//写内部MAC或者外部MAC
                    product.MAC = msg.ProductMac;
                else
                    product.YCD_MAC = msg.ProductMac;

                product.FLOW_ID = _sta.FLOW_ID;
                product.LINE_ID = _sta.LINE_ID;
                product.NODE_ID = _sta.NODE_ID;
                product.TEST_RESULT = "N";
                product.START_TIME = DateTime.Now;
                product.STATE = false;//标识产品开始
                product.NODE_STATE = false;//标识工序开始
                product.BREAK_STATE = false;//报废标识为0，不报废
            }
            //有产品数据的情况
            else
            {
                //获取当前产品的信息
                var selectPro = MethodWcf.SelectProductClient(product);
                if (selectPro.result)
                {
                    var last = selectPro.value[0];
                    //测试结果
                    if (last.TEST_RESULT == "Y")
                    {
                        SetPassOrNotPass();
                    }
                    else
                    {
                        SetPassOrNotPass(false);
                    }

                    //工序名称
                    if (last.NODE_ID != null)
                    {
                        string nodeName = (from n in _listNode
                                           where n.ID == last.NODE_ID.Value
                                           select n.NAME).FirstOrDefault();

                        SetLastNodeName(nodeName);

                    }
                }

                //判断能否进行当前工序
                StartRequest request = new StartRequest()
                {
                    PRODUCT_MAC = msg.ProductMac,
                    STATION_MAC = _sta.MAC
                };

                AppendRichTextBox("申请测试……");
                var canStart = MethodWcf.CanStartClient(request);

                AppendRichTextBox(string.Format("申请结果：{0}，MAC：{1}", canStart.message, msg.ProductMac));
                if (!canStart.result)//不能进行此道工序
                {
                    msg.RetResult = false;
                    msg.Message = string.Format("{0}，MAC：{1}", canStart.message, msg.ProductMac);

                    TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(msg), socket);
                    return;
                }

                //保存过程信息
                //修改产品信息，where条件在最上面的位置
                product.SetUpdate();
                product.FLOW_ID = _sta.FLOW_ID;
                product.LINE_ID = _sta.LINE_ID;
                product.NODE_ID = _sta.NODE_ID;
                product.NODE_STATE = false;//工序设置为开始

            }

            //有可能会发生测试几次的情况，所以先将相应的信息删除掉

            lock (_listProduct)
            {
                var productlist = (from p in _listProduct
                                   where p.MAC == msg.ProductMac || p.YCD_MAC == msg.ProductMac
                                   select p).ToList();

                for (int i = 0; productlist != null && productlist.Count > 0 && i < productlist.Count; i++)
                {
                    _listProduct.Remove(productlist[i]);
                }

                _listProduct.Add(product);//添加产品到list中
            }

            //判断是否需要写过程信息，如有之前有就删除掉

            lock (_listProcess)
            {
                var processlist = (from p in _listProcess
                                   where p.MAC == msg.ProductMac
                                   select p).ToList();

                for (int i = 0; processlist != null && processlist.Count > 0 && i < processlist.Count; i++)
                {
                    _listProcess.Remove(processlist[i]);
                }

                //添加过程信息
                PROCESS pro = new PROCESS();
                pro.SetUpdate();//需要写入的数据
                pro.MAC = msg.ProductMac;
                pro.WORKER_ID = _sta.WORKER_ID;
                pro.WORKER_NAME = _sta.WORKER_NAME;
                pro.FLOW_ID = _sta.FLOW_ID;
                pro.LINE_ID = _sta.LINE_ID;
                pro.NODE_ID = _sta.NODE_ID;
                pro.STATION_ID = _sta.ID;//保存站位信息
                pro.START_TIME = DateTime.Now;

                _listProcess.Add(pro);
            }

            AppendRichTextBox("");

            msg.RetResult = true;
            msg.Message = string.Format("{0}，MAC：{1}", "此工序可以进行", msg.ProductMac);

            TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(msg), socket);

        }
        //返回测试结果
        //只有写入过过程数据的MAC才可以提交测试结果
        private void SaveTestResultMsg(/*string guid,*/ TestResultMsg testResultMsg, System.Net.Sockets.Socket socket)
        {
            ReturnMessage retMsg = new ReturnMessage();
            retMsg.ProductMac = testResultMsg.ProductMac;

            try
            {
                //判断是否能否写产品数据
                if (_listProcess == null || _listProcess.Count == 0)
                {
                    AppendRichTextBox(string.Format("过程信息为空，不可以写入结果，MAC：{0}", testResultMsg.ProductMac));
                    retMsg.Message = string.Format("过程信息为空，不可以写入结果，MAC：{0}", testResultMsg.ProductMac);
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                var process = (from p in _listProcess
                               where p.MAC == testResultMsg.ProductMac
                               select p).FirstOrDefault();

                if (process == null)
                {
                    AppendRichTextBox(string.Format("此产品未经过站检测，不能保存测试结果，MAC：{0}", testResultMsg.ProductMac));
                    retMsg.Message = string.Format("此产品未经过站检测，不能保存测试结果，MAC：{0}", testResultMsg.ProductMac);
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid, */JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                //写产品数据
                process.END_TIME = DateTime.Now;
                if (testResultMsg.TestResult)
                {
                    process.TEST_RESULT = "Y";
                }
                else
                {
                    process.TEST_RESULT = "N";
                }

                ResultSet insertProc = MethodWcf.InsertProcessClient(process);

                if (insertProc.result == false)
                {
                    AppendRichTextBox(string.Format("写入过程数据失败，错误信息为：{0}，MAC：{1}", insertProc.message, testResultMsg.ProductMac));
                    retMsg.Message = string.Format("写入过程数据失败，错误信息为：{0}，MAC：{1}", insertProc.message, testResultMsg.ProductMac);
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid, */JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                AppendRichTextBox("写入结果成功");
                process.ID = long.Parse(insertProc.message);//保存过程的ID

                //写产品数据
                PRODUCT product = (from p in _listProduct
                                   where p.MAC == testResultMsg.ProductMac || p.YCD_MAC == testResultMsg.ProductMac
                                   select p).FirstOrDefault();

                if (product == null)
                {
                    AppendRichTextBox(string.Format("没有查到此产品申请过站的信息，MAC：{0}", testResultMsg.ProductMac));
                    retMsg.Message = string.Format("没有查到此产品申请过站的信息，MAC：{0}", testResultMsg.ProductMac);
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                //product.SetWhere();
                //product.MAC = testResultMsg.ProductMac;
                product.SetUpdate();

                if (testResultMsg.TestResult)
                {
                    product.TEST_RESULT = "Y";
                }
                else
                {
                    product.TEST_RESULT = "N";
                }

                product.NODE_STATE = true;
                product.END_TIME = DateTime.Now;//将结束事件设置为当前工序的结束时间
                product.FLOW_ID = _sta.FLOW_ID;
                product.NODE_ID = _sta.NODE_ID;


                AppendRichTextBox("更新产品信息……");
                ResultSet updateProductRes = null;

                //更新产品信息
                if (product.GetListWhere().Count == 0)
                {
                    updateProductRes = MethodWcf.InsertProductClient(product);
                }
                else
                {
                    updateProductRes = MethodWcf.UpdateProductClient(product);
                }

                //删除产品数据
                lock (_listProduct)
                    _listProduct.Remove(product);

                if (updateProductRes.result == false)
                {
                    AppendRichTextBox(string.Format("写入产品数据失败，错误信息为：{0}，MAC：{1}", updateProductRes.message, testResultMsg.ProductMac));
                    retMsg.Message = string.Format("写入产品失败，错误信息为：{0}，MAC：{1}", updateProductRes.message, testResultMsg.ProductMac);
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                AppendRichTextBox("更新产品结果：成功");

                retMsg.Message = string.Format("测试结果写入成功，MAC：{0}", testResultMsg.ProductMac);
                retMsg.RetResult = true;

                TcpSendMsg(/*guid, */JsonConvert.SerializeObject(retMsg), socket);
            }
            catch (Exception ex)
            {
                retMsg.Message = string.Format("保存测试结果失败：{0}，MAC：{1}", ex.Message, testResultMsg.ProductMac);
                retMsg.RetResult = false;

                TcpSendMsg(/*guid, */JsonConvert.SerializeObject(retMsg), socket);
            }
        }

        //写测试数据
        private void SaveTestLog(/*string guid, */TestSaveLog testLog, System.Net.Sockets.Socket socket)
        {
            //判断MAC是否存在于过程表中
            //判断过程表中的ID是否为null

            ReturnMessage retMsg = new ReturnMessage();
            retMsg.ProductMac = testLog.ProductMac;

            try
            {
                var process = (from p in _listProcess
                               where p.MAC == testLog.ProductMac
                               select p).FirstOrDefault();

                if (process == null)
                {
                    AppendRichTextBox(string.Format("未查到过程信息，不能保存测试LOG，MAC：{0}", testLog.ProductMac));
                    retMsg.Message = string.Format("未查到过程信息，不能保存测试LOG");
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid, */JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                if (process.ID <= 0)
                {
                    AppendRichTextBox(string.Format("过程信息未保存或保存失败，不能保存LOG，MAC：{0}，ID：{1}", testLog.ProductMac, process.ID));
                    retMsg.Message = string.Format("过程信息未保存或保存失败，不能保存LOG，MAC：{0}，ID：{1}", testLog.ProductMac, process.ID);
                    retMsg.RetResult = false;
                    TcpSendMsg(/*guid, */JsonConvert.SerializeObject(retMsg), socket);
                    return;
                }

                //写测试log
                var testTop = new TEST_TOP();
                testTop.SetUpdate();
                testTop.PROCESS_ID = process.ID;
                testTop.PROJECT = _sta.NAME;//测试站位名称
                if (testLog.TestResult)
                {
                    testTop.RESULT = "Y";
                }
                else
                {
                    testTop.RESULT = "N";
                }
                testTop.CONTEXT = testLog.TestLog;

                var insertTestLog = MethodWcf.InsertTestTopClient(testTop);

                //保存成功
                lock (_listProcess)
                    _listProcess.Remove(process);


                //保存测试LOG
                AppendRichTextBox(string.Format("保存测试LOG成功，MAC：{0}", testLog.ProductMac));
                retMsg.Message = string.Format("保存测试LOG成功，MAC：{0}", testLog.ProductMac);
                retMsg.RetResult = true;
                TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(retMsg), socket);

            }
            catch (Exception ex)
            {
                retMsg.Message = string.Format("保存测试log失败：{0}，MAC：{1}", ex.Message, testLog.ProductMac);
                retMsg.RetResult = false;

                TcpSendMsg(/*guid,*/ JsonConvert.SerializeObject(retMsg), socket);
            }
        }

        private void _tcpServer_OnAccept(int obj)
        {
            AppendRichTextBox(string.Format("已经连接了TCP客户端[{0}]", obj));
        }

        //将信息检查信息窗口
        private void AppendRichTextBox(string value)
        {
            if (this.richTextBoxTestMsg.InvokeRequired)
            {
                Action<string> d = new Action<string>(AppendRichTextBox);
                Invoke(d, value);
            }
            else
            {
                if (value == null) return;
                if (this.richTextBoxTestMsg.Text != null && this.richTextBoxTestMsg.TextLength >= 5000)
                    this.richTextBoxTestMsg.Clear();
                if (this.richTextBoxTestMsg != null)
                {
                    this.richTextBoxTestMsg.AppendText(value);
                    this.richTextBoxTestMsg.AppendText("\n");
                }
            }
        }

        private void RichTextBoxTestMsg_TextChanged(object sender, EventArgs e)
        {
            richTextBoxTestMsg.SelectionStart = richTextBoxTestMsg.Text.Length;
            richTextBoxTestMsg.ScrollToCaret();
        }

        /// <summary>
        /// 设置产品合格或者不合格
        /// </summary>
        /// <param name="pass"></param>
        private void SetPassOrNotPass(bool pass = true)
        {
            if (this.textBoxTestResult.InvokeRequired)
            {
                Action<bool> d = new Action<bool>(SetPassOrNotPass);
                Invoke(d, new object[] { pass });
            }
            else
            {
                if (pass)
                {
                    this.textBoxTestResult.Text = "通过";
                    this.textBoxTestResult.BackColor = Color.Green;
                }
                else
                {
                    this.textBoxTestResult.Text = "不通过";
                    this.textBoxTestResult.BackColor = Color.Red;
                }
            }

        }

        /// <summary>
        /// 设置上一个工序名称
        /// </summary>
        /// <param name="name"></param>
        private void SetLastNodeName(string name)
        {
            if (this.textBoxLastNodeName.InvokeRequired)
            {
                Action<string> d = new Action<string>(SetLastNodeName);
                Invoke(d, name);
            }
            else
            {
                this.textBoxLastNodeName.Text = name;
            }
        }

        private void FormBackGround_FormClosed(object sender, FormClosedEventArgs e)
        {
            //_tcpServer.Stop();
            //_formSta.Show();//窗体显示
            //_formSta.WindowState = FormWindowState.Normal;  //窗体状态默认大小  
            //_formSta.Activate(); //激活窗体给予焦点

        }

        private void FormBackGround_FormClosing(object sender, FormClosingEventArgs e)
        {
            //窗体关闭原因为单击"关闭"按钮或Alt+F4  
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;           //取消关闭操作 表现为不关闭窗体  
            }
        }

        #region 自动缩放

        private float X = 0.0f;
        private float Y = 0.0f;

        private void setTag(Control cons)
        {
            foreach (Control con in cons.Controls)
            {
                con.Tag = con.Width + ":" + con.Height + ":" + con.Top + ":" + con.Left + ":" + con.Font.Size;
                if (con.Controls.Count > 0)
                {
                    setTag(con);
                }
            }
        }
        private void setControls(float newx, float newy, Control cons)
        {
            foreach (Control con in cons.Controls)
            {
                String[] mytags = con.Tag.ToString().Split(new char[] { ':' });
                float a = Convert.ToSingle(mytags[0]) * newx;
                con.Width = (int)a;
                a = Convert.ToSingle(mytags[1]) * newy;
                con.Height = (int)a;
                a = Convert.ToSingle(mytags[2]) * newy;
                con.Top = (int)a;
                a = Convert.ToSingle(mytags[3]) * newx;
                con.Left = (int)a;
                Single currectsize = Convert.ToSingle(mytags[4]) * newy;
                con.Font = new Font(con.Font.Name, currectsize, con.Font.Style, con.Font.Unit);
                if (con.Controls.Count > 0)
                {
                    setControls(newx, newy, con);
                }
            }
        }

        private void Form_Resize(object sender, EventArgs e)
        {
            float newX = this.Width / X;
            float newY = this.Height / Y;

            setControls(newX, newY, this);
            //this.Text = this.Width.ToString() + "*" + this.Height.ToString();
        }

        #endregion

        #region 超级后台
        private void FormBackGround_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //打开超级后台功能
            bool visable = this.checkBoxBigBackGround.Visible;
            this.checkBoxBigBackGround.Visible = !visable;
        }

        private void checkBoxBigBackGround_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBoxBigBackGround.Checked)
            {
                PasswordInput pass = new PasswordInput();
                if (pass.ShowDialog() == DialogResult.Cancel)
                    this.checkBoxBigBackGround.Checked = false;
            }
        }
        #endregion
    }
}
